package com.filebackup.daemon;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.filebackup.cloudapi.CloudApiFactory;

public class DaemonBoss implements IBoss {

	private static DaemonBoss instance = new DaemonBoss();

	private Map<String, List<DownloadWorker>> downloadWorkers;
	private Map<String, List<UploadWorker>> uploadWorkers;

	private static int jobId = 0;

	private static final int WORKERNUM_PERAPI = 2;

	private DaemonBoss() {
		init();
	}

	private void init() {
		int id = 0;

		/**
		 * downloadWorkers = new HashMap<String, List<DownloadWorker>>();
		 * 
		 * String[] apiNames = CloudApiFactory.getInstance().getApiNames();
		 * 
		 * for (String name : apiNames) { List<DownloadWorker>
		 * downloadWorkerList = new ArrayList<DownloadWorker>();
		 * 
		 * for (int i = 0; i < WORKERNUM_PERAPI; i++) { DownloadWorker
		 * downloadWorker = new DownloadWorker(id++, name,
		 * CloudApiFactory.getApi(name));
		 * 
		 * downloadWorkerList.add(downloadWorker);
		 * 
		 * downloadWorker.start(); }
		 * 
		 * downloadWorkers.put(name, downloadWorkerList); }
		 */

		uploadWorkers = new HashMap<String, List<UploadWorker>>();

		String[] apiNames = CloudApiFactory.getInstance().getApiNames();

		for (String name : apiNames) {
			List<UploadWorker> uploadWorkerList = new ArrayList<UploadWorker>();

			for (int i = 0; i < WORKERNUM_PERAPI; i++) {
				UploadWorker uploadWorker = new UploadWorker(id++, name,
						CloudApiFactory.getApi(name));

				uploadWorkerList.add(uploadWorker);

				uploadWorker.start();
			}

			uploadWorkers.put(name, uploadWorkerList);
		}

	}

	public void stop() {
		Collection<List<DownloadWorker>> downloadWorkerLists = downloadWorkers
				.values();
		Iterator<List<DownloadWorker>> itr = downloadWorkerLists.iterator();

		while (itr.hasNext()) {
			List<DownloadWorker> list = itr.next();
			for (DownloadWorker worker : list) {
				worker.stop();
			}
		}

		Collection<List<UploadWorker>> uploadWorkerLists = uploadWorkers
				.values();
		Iterator<List<UploadWorker>> itr2 = uploadWorkerLists.iterator();

		while (itr2.hasNext()) {
			List<UploadWorker> list = itr2.next();
			for (UploadWorker worker : list) {
				worker.stop();
			}
		}
	}

	public static DaemonBoss getInstance() {
		return instance;
	}

	public void submitUploadJob(String cloudFile,
			String sourceFile) {
		UploadJob job = new UploadJob(jobId++, cloudFile, sourceFile);
		this.assignUploadJob(job);
	}

	public void submitDownloadJob(String cloudFile,
			String saveFile) {
		DownloadJob job = new DownloadJob(jobId++, cloudFile,
				saveFile);
		this.assignDownloadJob(job);
	}

	private void assignUploadJob(UploadJob job) {

		Iterator<List<UploadWorker>> itr = uploadWorkers.values().iterator();
		while (itr.hasNext()) {
			UploadWorker worker = this.selectUploadWorker(itr.next());

			worker.assignJob(job);

			System.out
					.println("assign uploadjob:" + job.sourceFile
							+ " to worker:" + worker.workerId + " "
							+ worker.workerName);
		}

	}

	private void assignDownloadJob(DownloadJob job) {
		// this.selectDownloadWorker().assignJob(job);
	}

	private DownloadWorker selectDownloadWorker(
			List<DownloadWorker> downloadWorkerList) {

		DownloadWorker thatWorker = null;
		long min = Long.MAX_VALUE;

		Iterator<DownloadWorker> itr = downloadWorkerList.iterator();
		while (itr.hasNext()) {
			DownloadWorker worker = itr.next();
			long jobSize = worker.getListJobSize();
			if (min > jobSize) {
				min = jobSize;
				thatWorker = worker;
			}
		}

		return thatWorker;
	}

	private UploadWorker selectUploadWorker(List<UploadWorker> uploadWorkerList) {
		UploadWorker thatWorker = null;
		long min = Long.MAX_VALUE;

		Iterator<UploadWorker> itr = uploadWorkerList.iterator();
		while (itr.hasNext()) {
			UploadWorker worker = itr.next();
			long jobSize = worker.getListJobSize();
			if (min > jobSize) {
				min = jobSize;
				thatWorker = worker;
			}
		}

		System.out.println("the right uploadworker is:" + thatWorker.workerId
				+ " " + thatWorker.workerName);

		return thatWorker;
	}
}
